package com.itheima.tanhua.dubbo.mongo.api.impl;

import cn.hutool.core.collection.CollUtil;
import com.itheima.tanhua.api.MovementApi;
import com.itheima.tanhua.dubbo.mongo.utils.IdWorker;
import com.itheima.tanhua.mongo.Movement;
import com.itheima.tanhua.mongo.MovementTimeLine;
import com.itheima.tanhua.vo.PageResult;
import org.apache.dubbo.config.annotation.DubboService;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.List;

@DubboService
public class MovementApiImpl implements MovementApi {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private IdWorker idWorker;

    @Autowired
    private PublisherApi publisherApi;

    /**
     * 发布动态
     * 1.添加动态信息到表movement
     * 2. 根据当前用户查询friend表
     * 3. 添加数据到movenment_timeline
     *
     * @param movement
     */
    @Override
    public String publisher(Movement movement) {
        // 1.添加动态信息到表movement
            //自动生成pid并且设置到movement
        //设置id
        movement.setId(ObjectId.get());
        movement.setPid(idWorker.getNextId("movement"));
        //填充发布时间
        movement.setCreated(System.currentTimeMillis());
        //添加
        mongoTemplate.save(movement);
        //操作 friend表和movement_timeline
        publisherApi.publisher(movement.getId(), movement.getUserId());
        return movement.getId().toHexString();
    }

    /**
     * 分页查询
     *
     * @param userId
     * @param page
     * @param pagesize
     * @return
     */
    @Override
    public PageResult getMovementsByUserId(Long userId, Integer page, Integer pagesize) {
        //构建Cra
        Criteria criteria = Criteria.where("userId").is(userId).and("state").is(1);
        Query q = Query.query(criteria)
                .skip((page - 1) * pagesize)//计算页数 出第二页-->从11开始 也就是跳过前十条数据
                .limit(pagesize)
                .with(Sort.by(Sort.Order.desc("created")));//每一页的条数
        List<Movement> results = mongoTemplate.find(q, Movement.class);
        //填充pr
        PageResult pr = new PageResult(page, pagesize, 0l, results);
        //返回
        return pr;
    }

    /**
     * 获取好友动态
     *
     * @param page
     * @param pagesize
     * @param friendId
     * @return
     */
    @Override
    public List<Movement> findFriendMovements(Integer page, Integer pagesize, Long friendId) {
        //根据friendId查询时间线表
        Criteria criteria = Criteria.where("friendId").is(friendId);
        Query created = Query.query(criteria).skip((page - 1) * pagesize) //分页查询 按照时间降序排序
                .limit(pagesize).with(Sort.by(Sort.Order.desc("created")));
        List<MovementTimeLine> movementTimeLines = mongoTemplate.find(created, MovementTimeLine.class);
        //提取动态id
        List<ObjectId> movementIds = CollUtil.getFieldValues(movementTimeLines, "movementId", ObjectId.class);
        //根据动态id查询动态
        Criteria movementCriteria = Criteria.where("id").in(movementIds).and("state").is(1);
        Query query = Query.query(movementCriteria);
        //返回结果
        return mongoTemplate.find(query, Movement.class);
    }

    /**
     * 随机获取推荐数据
     *
     * @param count 数量
     * @return
     */
    @Override
    public List<Movement> randomRecommendMovements(Integer count) {
        TypedAggregation aggregation =
                Aggregation.newAggregation(Movement.class, Aggregation.sample(count));//随机获取count条动态
        AggregationResults<Movement> aggregate = mongoTemplate.aggregate(aggregation, Movement.class);
        //返回数据
        return aggregate.getMappedResults();
    }

    /**
     * 获取推荐动态 根据pid
     *
     * @param pidList
     * @return
     */
    @Override
    public List<Movement> findRecommendMovements(List<Long> pidList) {
        //构建Criteria
        Criteria pid = Criteria.where("pid").in(pidList).and("state").is(1);
        Query query = Query.query(pid);
        return mongoTemplate.find(query, Movement.class);
    }

    /**
     * 根据id查询指定动态
     *
     * @param movementId
     * @return
     */
    @Override
    public Movement findOneById(String movementId) {
        //构建Criteria
        ObjectId objectId = new ObjectId(movementId);
        Criteria criteria = Criteria.where("id").is(objectId);
        Query query = Query.query(criteria);
        Movement result = mongoTemplate.findOne(query, Movement.class);
        return result;
    }

    /**
     * 分页查询指定用户
     * 指定status的动态
     *
     * @param page      页码
     * @param pagesize  页尺寸
     * @param uid       用户id
     * @param status    状态
     * @param sortProp  排序字段
     * @param sortOrder 排序规则
     * @return
     */
    @Override
    public PageResult findMovementById(Integer page, Integer pagesize, Long uid, Integer status, String sortProp, String sortOrder) {
        Query query = new Query();
        if (uid != null) {
            query.addCriteria(Criteria.where("userId").is(uid));
        }
        if (status != null) {
            query.addCriteria(Criteria.where("state").is(status));
        }
        //统计数量
        long count = mongoTemplate.count(query, Movement.class);
        query.skip((page - 1) * pagesize)
                .limit(pagesize);
        if (sortProp != null) {
            if (sortProp != null && sortOrder.equals("ascending")) {
                query.with(Sort.by(Sort.Order.asc(sortProp)));
            } else {
                query.with(Sort.by(Sort.Order.desc(sortProp)));
            }
        }
        List<Movement> movements = mongoTemplate.find(query, Movement.class);
        if (CollUtil.isEmpty(movements)) {
            return new PageResult();
        }

        PageResult pageResult = new PageResult(page, pagesize, count, movements);
        //返回数据
        return pageResult;
    }

    /**
     * 根据动态id修改动态状态
     *
     * @param movementId
     * @param state
     */
    @Override
    public void updateById(String movementId, Integer state) {
        Query up = Query.query(Criteria.where("id").is(new ObjectId(movementId)));
        Update update = new Update();
        update.set("state", state);
        //修改
        mongoTemplate.updateFirst(up, update, Movement.class);
    }
}